﻿using System;
using System.Reflection;
using System.Collections.Generic;

using Server.Multis;

namespace Server.Items
{
	[AttributeUsage( AttributeTargets.Class )]
	public class FlipableAddonAttribute : Attribute
	{
		private static string m_MethodName = "Flip";
		private static Type[] m_Params = new Type[] 
		{
			typeof( Mobile ), typeof( Direction )
		};

		private Direction[] m_Directions;

		public Direction[] Directions
		{
			get { return m_Directions; }
		}

		public FlipableAddonAttribute( params Direction[] directions )
		{
			m_Directions = directions;
		}

		public virtual void Flip( Mobile from, Item addon )
		{
			if ( m_Directions != null && m_Directions.Length > 1 )
			{
				try
				{
					MethodInfo flipMethod = addon.GetType().GetMethod( m_MethodName, m_Params );

					if ( flipMethod != null )
					{						
						int index = 0;

						for ( int i = 0; i < m_Directions.Length; i++ )
						{
							if ( addon.Direction == m_Directions[ i ] )
							{
								index = i + 1;
								break;
							}
						}

						if ( index >= m_Directions.Length )
							index = 0;

						ClearComponents( addon );

						flipMethod.Invoke( addon, new object[ 2 ]{ from, m_Directions[ index ] } );

						BaseHouse house = null;
						AddonFitResult result = AddonFitResult.Valid;

						addon.Map = Map.Internal;	

						if ( addon is BaseAddon )
							result = ((BaseAddon) addon).CouldFit( addon.Location, from.Map, from, ref house );
						else if ( addon is BaseAddonContainer )
							result = ((BaseAddonContainer) addon).CouldFit( addon.Location, from.Map, from, ref house );

						addon.Map = from.Map;

						if ( result != AddonFitResult.Valid )
						{
							if ( index == 0 )
								index = m_Directions.Length - 1;
							else
								index -= 1;
							
							ClearComponents( addon );

							flipMethod.Invoke( addon, new object[ 2 ]{ from, m_Directions[ index ] } );

							if ( result == AddonFitResult.Blocked )
								from.SendLocalizedMessage( 500269 ); // You cannot build that there.
							else if ( result == AddonFitResult.NotInHouse )
								from.SendLocalizedMessage( 500274 ); // You can only place this in a house that you own!
							else if ( result == AddonFitResult.DoorsNotClosed )
								from.SendMessage( "You must close all house doors before placing this." );
							else if ( result == AddonFitResult.DoorTooClose )
								from.SendLocalizedMessage( 500271 ); // You cannot build near the door.
							else if ( result == AddonFitResult.NoWall )
								from.SendLocalizedMessage( 500268 ); // This object needs to be mounted on something.
						}
						
						addon.Direction = m_Directions[ index ];
					}
				}
				catch
				{
				}
			}
		}

		private void ClearComponents( Item item )
		{
			if ( item is BaseAddon )
			{
				BaseAddon addon = (BaseAddon) item;

				foreach ( AddonComponent c in addon.Components )
				{
					c.Addon = null;
					c.Delete();
				}

				addon.Components.Clear();
			}
			else if ( item is BaseAddonContainer )
			{
				BaseAddonContainer addon = (BaseAddonContainer) item;

				foreach ( AddonContainerComponent c in addon.Components )
				{
					c.Addon = null;
					c.Delete();
				}

				addon.Components.Clear();
			}
		}
	}
}
